﻿// ===============================================================================
// XCI.NET 西安交通信息WinForm开发框架 2018 版权所有
// ===============================================================================

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Reflection;
using XCI.Helper;

namespace XCI.Core
{
    /// <summary>
    /// 行政区域管理
    /// </summary>
    public static class AreaDataManager
    {
        private static readonly Dictionary<string, AreaModel> All = new Dictionary<string, AreaModel>(48000);
        private static readonly List<AreaModel> Trees = new List<AreaModel>(48000);
        private static ReadOnlyCollection<AreaModel> TreeReadOnlyCollection;

        //省
        private static ReadOnlyCollection<AreaModel> Provinces;
        //市
        private static Dictionary<string, ReadOnlyCollection<AreaModel>> Citys;
        //区
        private static Dictionary<string, ReadOnlyCollection<AreaModel>> Countys;
        //街道
        private static Dictionary<string, ReadOnlyCollection<AreaModel>> Towns;

        static AreaDataManager()
        {
            //var msg = DebugHelper.StartWatch(LoadData, "省市区数据加载耗时");
            //MessageBox.Show(msg);
            //初始化数据
            LoadData();
        }

        public static void LoadData()
        {
            //读取省份数据
            Provinces = LoadProvince();

            //读取城市数据
            Citys = LoadChildrenData("city.json", 2);

            //读取区数据
            Countys = LoadChildrenData("county.json", 3);

            //读取街道数据
            Towns = LoadChildrenData("town.json", 4);
        }

        private static ReadOnlyCollection<AreaModel> LoadProvince()
        {
            var provinceFile = new JsonFile<List<AreaModel>>(Path.Combine(IOHelper.DataDirectory, "province.json"));
            provinceFile.Data.ForEach(model =>
            {
                ProcessModel(model, "0", 1);
            });
            return new ReadOnlyCollection<AreaModel>(provinceFile.Data);
        }

        private static Dictionary<string, ReadOnlyCollection<AreaModel>> LoadChildrenData(string fileName, int type)
        {
            var dataFile = new JsonFile<Dictionary<string, List<AreaModel>>>(Path.Combine(IOHelper.DataDirectory, fileName));
            var dic = new Dictionary<string, ReadOnlyCollection<AreaModel>>();
            foreach (KeyValuePair<string, List<AreaModel>> pair in dataFile.Data)
            {
                var key = pair.Key;
                foreach (var model in pair.Value)
                {
                    ProcessModel(model, key, type);
                }
                dic.Add(key, new ReadOnlyCollection<AreaModel>(pair.Value));
            }
            return dic;
        }

        private static void ProcessModel(AreaModel model, string parentId, int type)
        {
            model.ParentId = parentId;
            model.Type = type;
            Trees.Add(model);
            All.Add(model.Id, model);
        }

        /// <summary>
        /// 获取省份信息
        /// </summary>
        public static ReadOnlyCollection<AreaModel> GetProvince()
        {
            return Provinces;
        }

        /// <summary>
        /// 获取城市信息
        /// </summary>
        /// <param name="provinceId">省份编码</param>
        public static ReadOnlyCollection<AreaModel> GetCity(string provinceId)
        {
            if (string.IsNullOrEmpty(provinceId)) return null;
            return Citys.TryGetValue(provinceId, out ReadOnlyCollection<AreaModel> list) ? list : null;
        }

        /// <summary>
        /// 获取区县信息
        /// </summary>
        /// <param name="cityId">城市编码</param>
        public static ReadOnlyCollection<AreaModel> GetCounty(string cityId)
        {
            if (string.IsNullOrEmpty(cityId)) return null;
            return Countys.TryGetValue(cityId, out ReadOnlyCollection<AreaModel> list) ? list : null;
        }

        /// <summary>
        /// 获取街道信息
        /// </summary>
        /// <param name="countyId">区县编码</param>
        public static ReadOnlyCollection<AreaModel> GetTown(string countyId)
        {
            if (string.IsNullOrEmpty(countyId)) return null;
            return Towns.TryGetValue(countyId, out ReadOnlyCollection<AreaModel> list) ? list : null;
        }

        public static AreaModel GetById(string id)
        {
            if (string.IsNullOrEmpty(id)) return null;
            return All.TryGetValue(id, out AreaModel model) ? model : null;
        }

        public static ReadOnlyCollection<AreaModel> GetTreeCollection()
        {
            if (TreeReadOnlyCollection != null) return TreeReadOnlyCollection;
            TreeReadOnlyCollection = Trees?.AsReadOnly();
            return TreeReadOnlyCollection;
        }

        public static DataObjectField GetDataObjectField(object dataObject)
        {
            var df = new DataObjectField();
            if (dataObject == null) return df;

            var pros = dataObject.GetType().GetProperties();
            foreach (PropertyInfo pro in pros)
            {
                var attr1 = ObjectHelper.GetAttribute<ProvinceIdAttribute>(pro);
                if (attr1 != null)
                {
                    df.ProvinceIdField = pro.Name;
                    continue;
                }

                var attr2 = ObjectHelper.GetAttribute<ProvinceNameAttribute>(pro);
                if (attr2 != null)
                {
                    df.ProvinceNameField = pro.Name;
                    continue;
                }

                var attr3 = ObjectHelper.GetAttribute<CityIdAttribute>(pro);
                if (attr3 != null)
                {
                    df.CityIdField = pro.Name;
                    continue;
                }

                var attr4 = ObjectHelper.GetAttribute<CityNameAttribute>(pro);
                if (attr4 != null)
                {
                    df.CityNameField = pro.Name;
                    continue;
                }

                var attr5 = ObjectHelper.GetAttribute<CountyIdAttribute>(pro);
                if (attr5 != null)
                {
                    df.CountyIdField = pro.Name;
                    continue;
                }

                var attr6 = ObjectHelper.GetAttribute<CountyNameAttribute>(pro);
                if (attr6 != null)
                {
                    df.CountyNameField = pro.Name;
                    continue;
                }

                var attr7 = ObjectHelper.GetAttribute<TownIdAttribute>(pro);
                if (attr7 != null)
                {
                    df.TownIdField = pro.Name;
                    continue;
                }

                var attr8 = ObjectHelper.GetAttribute<TownNameAttribute>(pro);
                if (attr8 != null)
                {
                    df.TownNameField = pro.Name;
                }
            }

            return df;
        }

        //private static void AddChilrenModel(List<AreaModel> collection, string id, Dictionary<string, ReadOnlyCollection<AreaModel>> dic, Action<string> action)
        //{
        //    if (dic.TryGetValue(id, out ReadOnlyCollection<AreaModel> children))
        //    {
        //        foreach (var item in children)
        //        {
        //            collection.Add(item);
        //            action?.Invoke(item.Id);
        //        }
        //    }
        //}

        //public static ReadOnlyCollection<AreaModel> GetTreeCollection()
        //{
        //    if (Trees != null) return Trees;
        //    var list = new List<AreaModel>();

        //    foreach (var province in Provinces)
        //    {
        //        list.Add(province);
        //        var provinceId = province.Id;
        //        AddChilrenModel(list, provinceId, Citys, cityId =>
        //        {
        //            AddChilrenModel(list, cityId, Countys, countyId =>
        //            {
        //                AddChilrenModel(list, countyId, Towns,null);
        //            });
        //        });
        //    }
        //    Trees = new ReadOnlyCollection<AreaModel>(list);
        //    return Trees;
        //}
    }
}